from flask import Flask, render_template, request, redirect, url_for, session, jsonify, flash
import pandas as pd
from datetime import datetime
import matplotlib

from Get_Qianfan import generate_course_data, generate_completion_chart, analyze_course_data

matplotlib.use('Agg')  # 使用非交互式后端避免线程问题
import matplotlib.pyplot as plt
import numpy as np
import io
import base64
import random

# 配置中文字体（兼容Windows系统）
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei', 'SimHei', 'WenQuanYi Micro Hei']
plt.rcParams['axes.unicode_minus'] = False

app = Flask(__name__)
app.secret_key = 'your_secret_key_here'  # 会话密钥

# 全局数据存储
users = {
    "teachers": {
        1: {"id": 1, "name": "王教授", "email": "teacher1@example.com", "password": "teacher123", "role": "teacher"},
        2: {"id": 2, "name": "李讲师", "email": "teacher2@example.com", "password": "teacher456", "role": "teacher"}
    },
    "students": {
        1: {"id": 1, "name": "张三", "email": "student1@example.com", "password": "student123", "role": "student"},
        2: {"id": 2, "name": "李四", "email": "student2@example.com", "password": "student456", "role": "student"},
        3: {"id": 3, "name": "王五", "email": "student3@example.com", "password": "student789", "role": "student"}
    }
}

courses = {
    1: {
        "id": 1,
        "title": "Python全栈开发",
        "description": "从基础语法到Web开发的全链路课程，适合0基础学员",
        "modules": [
            {"id": 1, "title": "Python基础语法", "duration": 45},
            {"id": 2, "title": "Web框架Flask", "duration": 60},
            {"id": 3, "title": "数据库实战", "duration": 50},
            {"id": 4, "title": "项目部署上线", "duration": 40}
        ],
        "difficulty": "中级",
        "enrollment_count": 1520,
        "completion_rate": 72.8,
        "tags": ["Python", "Web开发", "全栈"],
        "rating": 4.8,
        "related_courses": [2],
        "teacher_id": 1
    },
    2: {
        "id": 2,
        "title": "数据分析与可视化",
        "description": "掌握Python数据分析工具链，从数据清洗到可视化全流程",
        "modules": [
            {"id": 1, "title": "NumPy与Pandas", "duration": 70},
            {"id": 2, "title": "数据可视化Matplotlib", "duration": 60},
            {"id": 3, "title": "实战案例分析", "duration": 80}
        ],
        "difficulty": "中级",
        "enrollment_count": 1280,
        "completion_rate": 65.3,
        "tags": ["数据分析", "可视化", "Python"],
        "rating": 4.7,
        "related_courses": [1, 3],
        "teacher_id": 2
    }
}

# 初始化学习数据
learning_data = pd.DataFrame([
    {"user_id": 1, "course_id": 1, "module_id": 1, "time_spent": 50, "completed": True, "last_accessed": "2025-08-01"},
    {"user_id": 1, "course_id": 1, "module_id": 2, "time_spent": 65, "completed": True, "last_accessed": "2025-08-02"},
    {"user_id": 1, "course_id": 1, "module_id": 3, "time_spent": 40, "completed": False, "last_accessed": "2025-08-03"},
    {"user_id": 2, "course_id": 1, "module_id": 1, "time_spent": 45, "completed": True, "last_accessed": "2025-08-01"},
    {"user_id": 3, "course_id": 2, "module_id": 1, "time_spent": 75, "completed": True, "last_accessed": "2025-08-01"}
])

course_reviews = {
    1: [
        {"user_id": 1, "rating": 5, "comment": "课程内容很实用，老师讲解清晰", "date": "2025-08-05"},
        {"user_id": 2, "rating": 4, "comment": "项目部分可以再深入一些", "date": "2025-08-06"}
    ],
    2: [
        {"user_id": 3, "rating": 5, "comment": "可视化部分案例非常丰富", "date": "2025-08-07"}
    ]
}

# 学习笔记数据结构
course_notes = {
    1: {  # 用户ID
        1: {  # 课程ID
            1: [  # 模块ID
                {"id": 1, "content": "Python变量命名规则很重要", "created_at": "2025-08-01 10:30:00"},
                {"id": 2, "content": "列表和元组的区别需要牢记", "created_at": "2025-08-01 14:20:00"}
            ],
            2: [
                {"id": 1, "content": "Flask路由装饰器很实用", "created_at": "2025-08-02 09:15:00"}
            ]
        }
    },
    2: {
        1: {
            1: [
                {"id": 1, "content": "Python基础语法笔记", "created_at": "2025-08-01 11:30:00"}
            ]
        }
    }
}


# 推荐算法 - 基于完课率、评价和标签匹配
def get_recommendations(user_id=None, user_role="student", limit=3):
    global courses, learning_data

    if user_id and user_role == "student":
        # 获取学生已学课程
        user_courses = learning_data[learning_data['user_id'] == user_id]['course_id'].unique()
        user_tags = set()
        for cid in user_courses:
            if cid in courses:
                user_tags.update(courses[cid]['tags'])

        # 计算学生平均完课率
        user_completion_rates = []
        for cid in user_courses:
            if cid not in courses:
                continue
            course_data = learning_data[(learning_data['user_id'] == user_id) &
                                        (learning_data['course_id'] == cid)]
            total_modules = len(courses[cid]['modules'])
            completed_modules = course_data['completed'].sum()
            if total_modules > 0:
                user_completion_rates.append(completed_modules / total_modules)

        user_avg_completion = sum(user_completion_rates) / len(user_completion_rates) if user_completion_rates else 0.5

        # 计算课程推荐分数
        course_scores = {}
        for cid, course in courses.items():
            if cid in user_courses:
                continue

            # 标签匹配度
            tag_match = len(set(course['tags']) & user_tags)

            # 完课率匹配度
            completion_match = 1 - abs(user_avg_completion - (course['completion_rate'] / 100))

            # 综合评分
            score = (tag_match * 3) + (course['rating'] * 3) + (completion_match * 2) + (
                    course['enrollment_count'] / 1000 * 2)
            course_scores[cid] = score

        # 排序并返回推荐结果
        sorted_courses = sorted(course_scores.items(), key=lambda x: x[1], reverse=True)
        recommended_ids = [cid for cid, _ in sorted_courses[:limit]]
    else:
        # 未登录用户推荐热门课程
        sorted_courses = sorted(courses.values(), key=lambda x: (x['enrollment_count'], x['rating']), reverse=True)
        recommended_ids = [course['id'] for course in sorted_courses[:limit]]

    return [courses[cid] for cid in recommended_ids if cid in courses]


# 登录验证装饰器 - 新增：统一验证登录状态
def login_required(f):
    def decorated_function(*args, **kwargs):
        user = session.get('user')
        if not user:
            flash("请先登录", "warning")
            return redirect(url_for('login', next=request.url))  # 记录跳转前的URL
        return f(*args, **kwargs)

    decorated_function.__name__ = f.__name__
    return decorated_function


# 教师权限验证装饰器 - 新增：统一验证教师权限
def teacher_required(f):
    def decorated_function(*args, **kwargs):
        user = session.get('user')
        if not user:
            flash("请先登录", "warning")
            return redirect(url_for('login', next=request.url))
        if user['role'] != 'teacher':
            flash("您没有教师权限", "danger")
            return redirect(url_for('index'))
        return f(*args, **kwargs)

    decorated_function.__name__ = f.__name__
    return decorated_function


# 学生权限验证装饰器 - 新增：统一验证学生权限
def student_required(f):
    def decorated_function(*args, **kwargs):
        user = session.get('user')
        if not user:
            flash("请先登录", "warning")
            return redirect(url_for('login', next=request.url))
        if user['role'] != 'student':
            flash("您没有学生权限", "danger")
            return redirect(url_for('index'))
        return f(*args, **kwargs)

    decorated_function.__name__ = f.__name__
    return decorated_function


@app.route('/analytics')
@login_required  # 使用装饰器验证登录状态
def analytics():
    user = session.get('user')
    user_id = user.get('id')

    # 获取用户学习数据
    user_learning_data = learning_data[learning_data['user_id'] == user_id]

    # 计算学习概览
    completed_courses = len(user_learning_data[user_learning_data['completed'] == True]['course_id'].unique())
    in_progress_courses = len(user_learning_data[user_learning_data['completed'] == False]['course_id'].unique())
    total_time = round(user_learning_data['time_spent'].sum() / 60, 1)  # 转换为小时
    completion_rate = round((user_learning_data['completed'].sum() / len(user_learning_data)) * 100, 1) if len(
        user_learning_data) > 0 else 0

    # 生成课程分析数据
    course_analytics = []
    for course_id in user_learning_data['course_id'].unique():
        if course_id in courses:
            course_data = user_learning_data[user_learning_data['course_id'] == course_id]
            course_completion = round((course_data['completed'].sum() / len(course_data)) * 100, 1)
            course_analytics.append({
                "title": courses[course_id]['title'],
                "completion_rate": course_completion,
                "enrollment_count": courses[course_id]['enrollment_count']
            })

    # 生成容易放弃的模块数据
    module_dropoff = []
    for course in courses.values():
        for module in course['modules']:
            module_dropoff.append({
                "course_title": course['title'],
                "module_title": module['title'],
                "completion_rate": 30 + (module['id'] * 5)  # 示例数据
            })

    # 获取推荐课程
    recommendations = get_recommendations(user_id, user.get('role'))

    # 生成图表和分析数据
    course_data = generate_course_data()
    chart_url = generate_completion_chart(course_data)
    analysis = analyze_course_data(course_data)

    return render_template('analytics.html',
                           user=user,
                           completed_courses=completed_courses,
                           in_progress_courses=in_progress_courses,
                           total_time=total_time,
                           completion_rate=completion_rate,
                           course_analytics=course_analytics,
                           module_dropoff=module_dropoff,
                           recommendations=recommendations,
                           chart_url=chart_url,
                           analysis=analysis,
                           course_data=course_data)


# 生成教师端课程完课率图表
def generate_teacher_completion_chart(course_id):
    global courses, learning_data

    course = courses.get(course_id)
    if not course:
        return None

    modules = course['modules']
    module_titles = [m['title'] for m in modules]
    module_ids = [m['id'] for m in modules]

    completion_rates = []
    for mid in module_ids:
        mod_data = learning_data[(learning_data['course_id'] == course_id) &
                                 (learning_data['module_id'] == mid)]
        if len(mod_data) > 0:
            rate = (mod_data['completed'].sum() / len(mod_data)) * 100
            completion_rates.append(round(rate, 1))
        else:
            completion_rates.append(0)

    plt.figure(figsize=(12, 6))
    bars = plt.bar(module_titles, completion_rates, color=['#00A1FF', '#5ed935', '#f8ba00', '#ff2501', '#d31876'])
    plt.title(f'{course["title"]} - 模块完课率统计', fontsize=16)
    plt.xlabel('课程模块', fontsize=14)
    plt.ylabel('完课率 (%)', fontsize=14)
    plt.ylim(0, 100)
    plt.grid(axis='y', linestyle='--', alpha=0.7)
    plt.xticks(rotation=45, ha='right', fontsize=12)

    for bar in bars:
        height = bar.get_height()
        plt.text(bar.get_x() + bar.get_width() / 2., height,
                 f'{height}%', ha='center', va='bottom', fontsize=12)

    img = io.BytesIO()
    plt.savefig(img, format='png', bbox_inches='tight', dpi=100)
    img.seek(0)
    chart_url = base64.b64encode(img.getvalue()).decode()
    plt.close()

    return f"data:image/png;base64,{chart_url}"


# 生成学生端个人完课率图表
def generate_student_completion_chart(user_id):
    global courses, learning_data

    user_courses = learning_data[learning_data['user_id'] == user_id]['course_id'].unique()
    course_titles = [courses[cid]['title'] for cid in user_courses if cid in courses]

    completion_rates = []
    for cid in user_courses:
        if cid not in courses:
            continue
        course_data = learning_data[(learning_data['user_id'] == user_id) &
                                    (learning_data['course_id'] == cid)]
        total_modules = len(courses[cid]['modules'])
        completed_modules = course_data['completed'].sum()
        rate = (completed_modules / total_modules) * 100 if total_modules > 0 else 0
        completion_rates.append(round(rate, 1))

    plt.figure(figsize=(10, 6))
    colors = ['#00A1FF', '#5ed935', '#f8ba00', '#ff2501', '#d31876']
    plt.pie(completion_rates, labels=course_titles, autopct='%1.1f%%',
            startangle=90, colors=colors, textprops={'fontsize': 12})
    plt.title('个人课程完课率分布', fontsize=16)
    plt.axis('equal')

    img = io.BytesIO()
    plt.savefig(img, format='png', bbox_inches='tight', dpi=100)
    img.seek(0)
    chart_url = base64.b64encode(img.getvalue()).decode()
    plt.close()

    return f"data:image/png;base64,{chart_url}"


# 路由定义
@app.route('/')
def index():
    user = session.get('user')
    recommendations = get_recommendations() if not user else get_recommendations(user.get('id'), user.get('role'))
    return render_template('index.html',
                           courses=courses.values(),
                           user=user,
                           recommendations=recommendations)


@app.route('/login', methods=['GET', 'POST'])
def login():
    # 如果已登录，直接跳转到相应的仪表盘
    if session.get('user'):
        user = session.get('user')
        if user['role'] == 'teacher':
            return redirect(url_for('teacher_dashboard'))
        else:
            return redirect(url_for('student_dashboard'))

    if request.method == 'POST':
        role = request.form['role']
        email = request.form['email']
        password = request.form['password']

        target_users = users.get(role + "s", {})
        for user in target_users.values():
            if user['email'] == email and user['password'] == password:
                session['user'] = {
                    "id": user['id'],
                    "name": user['name'],
                    "role": user['role'],
                    "email": user['email']
                }
                flash("登录成功！", "success")

                # 跳转到登录前请求的页面，如果没有则跳转到对应角色的仪表盘
                next_page = request.args.get('next')
                if next_page:
                    return redirect(next_page)

                if user['role'] == 'teacher':
                    return redirect(url_for('teacher_dashboard'))
                else:
                    return redirect(url_for('student_dashboard'))

        flash("邮箱或密码错误，请重试", "danger")
    return render_template('login.html')


@app.route('/logout')
def logout():
    session.pop('user', None)
    flash("已成功登出", "info")
    return redirect(url_for('index'))


# 教师端仪表盘
@app.route('/teacher/dashboard')
@teacher_required  # 使用教师权限装饰器
def teacher_dashboard():
    user = session.get('user')
    teacher_courses = [course for course in courses.values() if course['teacher_id'] == user['id']]
    recommendations = get_recommendations(user['id'], "teacher")

    return render_template('teacher_dashboard.html',
                           user=user,
                           courses=teacher_courses,
                           recommendations=recommendations)


# 学生端仪表盘
@app.route('/student/dashboard')
@student_required  # 使用学生权限装饰器
def student_dashboard():
    user = session.get('user')

    # 获取用户已选课程
    user_courses = learning_data[learning_data['user_id'] == user['id']]['course_id'].unique()
    enrolled_courses = [courses[cid] for cid in user_courses if cid in courses]

    # 获取用户学习数据
    user_learning_data = learning_data[learning_data['user_id'] == user['id']].to_dict('records')

    # 生成完课率图表
    chart_url = generate_student_completion_chart(user['id'])

    # 获取推荐课程
    recommendations = get_recommendations(user['id'], "student")

    return render_template('student_dashboard.html',
                           user=user,
                           enrolled_courses=enrolled_courses,
                           user_learning_data=user_learning_data,
                           chart_url=chart_url,
                           recommendations=recommendations)


# 教师查看课程统计
@app.route('/teacher/course/<int:course_id>')
@teacher_required
def teacher_course_stats(course_id):
    user = session.get('user')
    course = courses.get(course_id)

    # 验证课程是否属于该教师
    if not course or course.get('teacher_id') != user['id']:
        flash("无权限访问该页面", "danger")
        return redirect(url_for('teacher_dashboard'))

    chart_url = generate_teacher_completion_chart(course_id)
    reviews = course_reviews.get(course_id, [])
    anonymous_reviews = []
    for i, review in enumerate(reviews, 1):
        anonymous_reviews.append({
            "id": i,
            "rating": review['rating'],
            "comment": review['comment'],
            "date": review['date']
        })

    return render_template('teacher_course_stats.html',
                           user=user,
                           course=course,
                           chart_url=chart_url,
                           reviews=anonymous_reviews)


# 教师添加课程
@app.route('/teacher/add_course', methods=['GET', 'POST'])
@teacher_required
def add_course():
    global courses

    user = session.get('user')

    if request.method == 'POST':
        title = request.form['title']
        description = request.form['description']
        difficulty = request.form['difficulty']
        tags = [tag.strip() for tag in request.form['tags'].split(',') if tag.strip()]

        new_id = max(courses.keys()) + 1 if courses else 1
        new_course = {
            "id": new_id,
            "title": title,
            "description": description,
            "modules": [],
            "difficulty": difficulty,
            "enrollment_count": 0,
            "completion_rate": 0,
            "tags": tags,
            "rating": 0,
            "related_courses": [],
            "teacher_id": user['id']
        }

        courses[new_id] = new_course
        flash("课程添加成功", "success")
        return redirect(url_for('teacher_dashboard'))

    return render_template('add_course.html', user=user)


# 教师添加课程模块
@app.route('/teacher/course/<int:course_id>/add_module', methods=['POST'])
@teacher_required
def add_module(course_id):
    global courses

    user = session.get('user')
    course = courses.get(course_id)

    if not course or course.get('teacher_id') != user['id']:
        return jsonify({"success": False, "message": "无权限操作"})

    title = request.form['title']
    duration = int(request.form['duration'])

    module_id = len(course['modules']) + 1
    course['modules'].append({
        "id": module_id,
        "title": title,
        "duration": duration
    })

    return jsonify({"success": True, "message": "模块添加成功"})


# 课程详情页
@app.route('/course/<int:course_id>')
def course_detail(course_id):
    global learning_data

    course = courses.get(course_id)
    if not course:
        flash("课程不存在", "danger")
        return redirect(url_for('index'))

    user = session.get('user')
    progress = 0
    is_enrolled = False
    user_notes = {}

    if user and user['role'] == 'student':
        # 检查是否已选课
        user_enrollments = learning_data[(learning_data['user_id'] == user['id']) &
                                         (learning_data['course_id'] == course_id)]
        is_enrolled = len(user_enrollments) > 0

        # 计算学习进度
        if is_enrolled:
            completed = user_enrollments['completed'].sum()
            progress = int((completed / len(course['modules'])) * 100) if len(course['modules']) > 0 else 0

            # 获取用户笔记
            if user['id'] in course_notes and course_id in course_notes[user['id']]:
                user_notes = course_notes[user['id']][course_id]

    related_courses = [courses[cid] for cid in course['related_courses'] if cid in courses]
    reviews = course_reviews.get(course_id, [])

    return render_template('course_detail.html',
                           course=course,
                           user=user,
                           progress=progress,
                           is_enrolled=is_enrolled,
                           related_courses=related_courses,
                           reviews=reviews,
                           notes=user_notes)


# 学生选课
@app.route('/course/<int:course_id>/enroll', methods=['POST'])
@student_required
def enroll_course(course_id):
    global courses, learning_data

    user = session.get('user')
    user_id = user['id']

    # 检查是否已选课
    existing = learning_data[(learning_data['user_id'] == user_id) &
                             (learning_data['course_id'] == course_id)]
    if len(existing) > 0:
        return jsonify({"success": False, "message": "您已选过该课程"})

    # 添加选课记录
    course = courses.get(course_id)
    if not course:
        return jsonify({"success": False, "message": "课程不存在"})

    # 为每个模块创建初始学习记录
    for module in course['modules']:
        new_record = {
            "user_id": user_id,
            "course_id": course_id,
            "module_id": module['id'],
            "time_spent": 0,
            "completed": False,
            "last_accessed": datetime.now().strftime("%Y-%m-%d")
        }
        learning_data = pd.concat([learning_data, pd.DataFrame([new_record])], ignore_index=True)

    # 更新课程报名人数
    courses[course_id]['enrollment_count'] += 1

    return jsonify({"success": True, "message": "选课成功"})


# 添加学习笔记接口
@app.route('/api/course/<int:course_id>/module/<int:module_id>/note', methods=['POST'])
@student_required
def add_note(course_id, module_id):
    global course_notes

    user = session.get('user')
    user_id = user['id']

    if course_id not in courses:
        return jsonify({"success": False, "message": "参数错误"})

    data = request.json
    content = data.get('content', '').strip()

    if not content:
        return jsonify({"success": False, "message": "笔记内容不能为空"})

    # 初始化用户笔记数据结构
    if user_id not in course_notes:
        course_notes[user_id] = {}
    if course_id not in course_notes[user_id]:
        course_notes[user_id][course_id] = {}
    if module_id not in course_notes[user_id][course_id]:
        course_notes[user_id][course_id][module_id] = []

    # 创建新笔记
    note_id = len(course_notes[user_id][course_id][module_id]) + 1
    new_note = {
        "id": note_id,
        "content": content,
        "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    }

    course_notes[user_id][course_id][module_id].append(new_note)

    return jsonify({"success": True, "message": "笔记添加成功", "note": new_note})


# 获取学习笔记接口
@app.route('/api/course/<int:course_id>/notes')
@student_required
def get_notes(course_id):
    user = session.get('user')
    user_id = user['id']

    if course_id not in courses:
        return jsonify({"success": False, "message": "参数错误"})

    notes = {}
    if user_id in course_notes and course_id in course_notes[user_id]:
        notes = course_notes[user_id][course_id]

    return jsonify({"success": True, "notes": notes})


# 删除学习笔记接口
@app.route('/api/course/<int:course_id>/module/<int:module_id>/note/<int:note_id>', methods=['DELETE'])
@student_required
def delete_note(course_id, module_id, note_id):
    global course_notes

    user = session.get('user')
    user_id = user['id']

    if course_id not in courses:
        return jsonify({"success": False, "message": "参数错误"})

    # 检查笔记是否存在
    if (user_id not in course_notes or
            course_id not in course_notes[user_id] or
            module_id not in course_notes[user_id][course_id]):
        return jsonify({"success": False, "message": "笔记不存在"})

    # 查找并删除笔记
    notes = course_notes[user_id][course_id][module_id]
    for i, note in enumerate(notes):
        if note['id'] == note_id:
            del notes[i]
            return jsonify({"success": True, "message": "笔记删除成功"})

    return jsonify({"success": False, "message": "笔记不存在"})


# 提交课程评价接口（学生）
@app.route('/api/course/<int:course_id>/review', methods=['POST'])
@student_required
def submit_review(course_id):
    global course_reviews, courses

    user = session.get('user')
    user_id = user['id']

    if course_id not in courses:
        return jsonify({"success": False, "message": "参数错误"})

    data = request.json
    rating = data.get('rating')
    comment = data.get('comment', '').strip()

    if not rating or rating < 1 or rating > 5:
        return jsonify({"success": False, "message": "评分必须为1-5星"})

    # 保存评价
    if course_id not in course_reviews:
        course_reviews[course_id] = []
    course_reviews[course_id].append({
        "user_id": user_id,
        "rating": rating,
        "comment": comment,
        "date": datetime.now().strftime("%Y-%m-%d")
    })

    # 更新课程评分
    ratings = [r['rating'] for r in course_reviews[course_id]]
    courses[course_id]['rating'] = round(sum(ratings) / len(ratings), 1)

    return jsonify({"success": True, "message": "评价提交成功"})


if __name__ == '__main__':
    # 禁用调试模式的多进程启动，避免重复初始化
    app.run(debug=True, use_reloader=False)
